﻿using Minio.DataModel;
using Modules.CheckIn;
using Modules.CheckIn.Entitys;
using Modules.Corp;
using Modules.Person;
using Modules.Project;
using Modules.Project.Entitys;
using Modules.Reports;
using PmSoft;
using PmSoft.ApplicationContext;

namespace ManagementApi.Models.CheckIn
{
    /// <summary>
    /// 人员考勤月统计返回实体
    /// </summary>
    public class CheckInDetailPersonDto
    {
        /// <summary>
        /// 人员Id
        /// </summary>
        public int PersonId { get; set; }

        /// <summary>
        /// 项目名称
        /// </summary>
        public string ProjectName { get; set; }

        /// <summary>
        /// 人员姓名
        /// </summary>
        public string PersonName { get; set; }

        /// <summary>
        /// 班组名称
        /// </summary>
        public string GroupName { get; set; }

        /// <summary>
        /// 所属公司
        /// </summary>
        public string CorpName { get; set; }

        /// <summary>
        /// 所属公司类型
        /// </summary>
        public string CorpTypeName { get; set; }

        /// <summary>
        /// 工种
        /// </summary>
        public string WorkTypeName { get; set; }

        /// <summary>
        /// 本月应考勤天数
        /// </summary>
        public double MonthCheckinAddDay { get; set; }

        /// <summary>
        /// 本月实际出勤天数
        /// </summary>
        public double MonthCheckinDay { get; set; }

        /// <summary>
        /// 缺勤天数
        /// </summary>
        public double AbsenceDay { get; set; }

        /// <summary>
        /// 到岗率
        /// </summary>
        public string PresenceRate { get; set; }

        /// <summary>
        /// 缺勤率
        /// </summary>
        public string AbsenceRate { get; set; }

        public int MemberId { get; set; }

        /// <summary>
        /// 是否现场管理人员
        /// </summary>
        public bool IsManager { get; set; }

        /// <summary>
        /// 工时
        /// </summary>
        public decimal WorkHours { get; set; }
    }

    public static partial class CheckInDetailPersonExceptions
    {
        /// <summary>
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="applicationContext"></param>
        /// <param name="projectInfo"></param>
        /// <returns></returns>
        public static CheckInDetailPersonDto AsDto(this CheckInDetail entity, IApplicationContext applicationContext, ProjectInfo? projectInfo = null)
        {
            var personService = ServiceAccessor.GetService<PersonService>();
            var projectGroupService = ServiceAccessor.GetService<ProjectGroupService>();
            var projectGroupMemberService = ServiceAccessor.GetService<ProjectGroupMemberService>();
            var projectCorpService = ServiceAccessor.GetService<ProjectCorpService>();
            var corpService = ServiceAccessor.GetService<CorpService>();
            var projectService = ServiceAccessor.GetService<ProjectService>();
            var reportProjectMonthService = ServiceAccessor.GetService<ReportProjectMonthService>();
            var checkinWorkHoursService = ServiceAccessor.GetService<CheckinWorkHoursService>();

            projectInfo ??= projectService.GetProjectInfo(entity.ProjectId);
            var projectGroup = projectGroupService.GetProjectGroup(entity.GroupId);
            var projectGroupMember = projectGroupMemberService.GetMember(entity.MemberId);
            var monthCheckinAddDays = reportProjectMonthService.GetReportProjectMonthByProjectId(entity.ProjectId);
            var checkinWorkHours = checkinWorkHoursService.GetCheckinWorkHoursByMonthAndMemberId(entity.Month, entity.MemberId);
            var projectCorp = projectCorpService.GetProjectCorpByProjectIdAndCorpId(entity.ProjectId, projectGroup?.CorpId ?? 0);
            var corpInfo = corpService.GetCorpInfo(projectGroup?.CorpId ?? 0);
            var personInfo = personService.GetPerson(entity.PersonId);

            CheckInDetailPersonDto dto = new();
            dto.PersonId = entity.PersonId;
            dto.PersonName = personInfo?.Name ?? string.Empty;
            dto.GroupName = projectGroup?.Name ?? string.Empty;
            dto.MemberId = projectGroupMember?.Id ?? 0;
            dto.IsManager = projectGroupMember?.IsManager ?? false;
            if (projectInfo?.LumpContractorCorpId == projectGroup?.CorpId)
            {
                dto.CorpTypeName = "总承包";
            }
            else
            {
                dto.CorpTypeName = projectCorp?.Role.GetDescription() ?? string.Empty;
            }
            dto.CorpName = corpInfo?.Name ?? string.Empty;
            dto.ProjectName = projectInfo?.Name ?? string.Empty;
            dto.MonthCheckinAddDay = monthCheckinAddDays.FirstOrDefault(a => a.Month == entity.Month)?.DaysThisMonthUnderConstruction ?? 0;
            dto.WorkHours = checkinWorkHours?.WorkHours ?? 0;
            dto.MonthCheckinDay = checkinWorkHours?.CheckinDay ?? 0;
            if (dto.MonthCheckinAddDay == 0)
            {
                dto.AbsenceDay = 0;
                dto.PresenceRate = "0.00";
                dto.AbsenceRate = "0.00";
                return dto;
            }
            dto.AbsenceDay = dto.MonthCheckinAddDay - dto.MonthCheckinDay;
            dto.PresenceRate = ((dto.MonthCheckinDay / dto.MonthCheckinAddDay) * 100).ToString("0.00");
            dto.AbsenceRate = ((dto.AbsenceDay / dto.MonthCheckinAddDay) * 100).ToString("0.00");
            return dto;
        }

        /// <summary>
        /// 将数据库模型转换成导出excel模型
        /// </summary>
        /// <param name="details"></param>
        /// <param name="projectInfo"></param>
        /// <param name="applicationContext"></param>
        /// <returns></returns>
        public static IEnumerable<Dictionary<string, string>> AsCheckDetailExportDtos(this IEnumerable<CheckInDetail> details, ProjectInfo projectInfo, IApplicationContext applicationContext)
        {
            var projectGroupService = applicationContext.GetService<ProjectGroupService>();
            var projectService = applicationContext.GetService<ProjectService>();
            var projectGroupMemberService = applicationContext.GetService<ProjectGroupMemberService>();
            var projectCorpService = applicationContext.GetService<ProjectCorpService>();
            var checkInDetailService = applicationContext.GetService<CheckInDetailService>();
            var checkinWorkHoursService = applicationContext.GetService<CheckinWorkHoursService>();
            var reportProjectMonthService = applicationContext.GetService<ReportProjectMonthService>();
            var personService = applicationContext.GetService<PersonService>();
            var corpService = applicationContext.GetService<CorpService>();

            //项目下所有班组
            var projectGroups = projectGroupService.GetProjectGroupsByProjectId(projectInfo.ProjectId);

            //所有成员
            var projectMembers = projectGroupMemberService.GetProjectGroupMembersByPersonIds(details.Select(a => a.PersonId));

            var personIds = details.Select(a => a.PersonId).Distinct();
            var persons = personService.GetPersons(personIds);

            //所有考勤关联企业
            var corps = corpService.GetCorpsByCorpIds(projectGroups.Select(a => a.CorpId));

            List<Dictionary<string, string>> exportDatas = new List<Dictionary<string, string>>();
            //成员考勤工时统计
            var monthCheckinDays = checkinWorkHoursService.GetCheckinWorkHoursByMonthsAndMemberIds(details.Select(a => a.Month), details.Select(a => a.MemberId), details.Select(a => a.ProjectId));
            //项目所有月报表
            var reportProjectMonths = reportProjectMonthService.GetReportProjectMonthByProjectId(projectInfo.ProjectId);
            var projectCorps = projectCorpService.GetProjectCorpsByProjectId(projectInfo.ProjectId);

            foreach (var item in details)
            {
                //在建天数
                var monthCheckinAddDay = reportProjectMonths.FirstOrDefault(a => a.Month == item.Month)?.DaysThisMonthUnderConstruction ?? 0;
                var monthCheckinDay = monthCheckinDays.FirstOrDefault(a => a.Month == item.Month && a.MemberId == item.MemberId && a.ProjectId == item.ProjectId)?.CheckinDay ?? 0;
                var AbsenceDay = monthCheckinAddDay - monthCheckinDay;
                string corpType = "";
                var group = projectGroups.FirstOrDefault(i => i.GroupId == item.GroupId);

                if (projectInfo?.LumpContractorCorpId == group?.CorpId)
                {
                    corpType = "总承包";
                }
                else
                {
                    corpType = projectCorps.FirstOrDefault(i => i.CorpId == group?.CorpId)?.Role.GetDescription() ?? string.Empty;
                }
                Dictionary<string, string> exportData = new Dictionary<string, string>();
                exportData["人员姓名"] = persons.FirstOrDefault(a => a.PersonId == item.PersonId)?.Name ?? string.Empty;
                exportData["所属项目"] = projectInfo?.Name ?? string.Empty;
                exportData["所属公司"] = corps.FirstOrDefault(a => a.CorpId == projectGroups.FirstOrDefault(i => i.GroupId == item.GroupId)?.CorpId)?.Name ?? string.Empty;
                exportData["公司类型"] = corpType;
                exportData["班组"] = projectGroups.FirstOrDefault(a => a.GroupId == item.GroupId)?.Name ?? string.Empty;
                exportData["工种"] = projectMembers.FirstOrDefault(a => a.PersonId == item.PersonId)?.Type?.GetDescription() ?? string.Empty;
                if (monthCheckinAddDay == 0)
                {
                    exportData["本月应考勤天数"] = monthCheckinAddDay.ToString();//本月在建天数=本月应考勤天数
                    exportData["本月实际出勤天数"] = monthCheckinDay.ToString();
                    exportData["缺勤天数"] = "0";
                    exportData["到岗率"] = "0.00";
                    exportData["缺勤率"] = "0.00";
                }
                else
                {
                    exportData["本月应考勤天数"] = monthCheckinAddDay.ToString();
                    exportData["本月实际出勤天数"] = monthCheckinDay.ToString();
                    exportData["缺勤天数"] = AbsenceDay.ToString();
                    exportData["到岗率"] = ((Convert.ToDecimal(monthCheckinDay) / Convert.ToDecimal(monthCheckinAddDay)) * 100).ToString("0.00");
                    exportData["缺勤率"] = (Convert.ToDecimal(AbsenceDay) / Convert.ToDecimal(monthCheckinAddDay) * 100).ToString("0.00");
                }
                var data = checkInDetailService.GetCheckInDetailPersonForm(item.MemberId, item.Month);
                for (int i = 1; i <= monthCheckinAddDay; i++)
                {
                    exportData[i + "日"] = data.Contains(i) ? "√" : "";
                }
                exportDatas.Add(exportData);
            }
            return exportDatas;
        }
    }
}